Skip to content

Add support for modbus over serial (RTU)#41

Draft
matthijskooijman wants to merge 3 commits into
tjhowse:masterfrom
3devo:serial-modbus
Draft

Add support for modbus over serial (RTU)#41
matthijskooijman wants to merge 3 commits into
tjhowse:masterfrom
3devo:serial-modbus

Conversation

@matthijskooijman
Copy link
Copy Markdown

This PR:

  • takes the core commit of PR WIP attempt to get serial and RS485 Modbus-RTU working #35 by @iconnor (the commit that actually enables serial support, leaving out a bunch of seemingly unrelated commits), rebasing it on top of current master.
  • changes the parity setting to even (as modbus mandates and my device implements, but is not implemented on all devices it seems, so this should really be made configurable)
  • Adds a new commit to make the slave address configurable (also per register, so you can service multiple slaves on a single bus). I later noticed that WIP attempt to get serial and RS485 Modbus-RTU working #35 also implemented this, but I think my commit is preferred because it allows per-register configuration of the slave address. I've used the "slave" field for configuring this instead of "unit", since it seems that pymodbus is deprecating the "unit" parameter for this in favor of "slave" (though I believe this is not released yet, so we still pass "unit" to pymodbus).

I'm marking this as a draft pullrequest, since I do still have some doubts about the implementation:

  • This adds a number of extra configuration variables which are extracted from the config by modbus4mqtt.py and then passed to modbus_interface.__init__() separately. I'm not sure if this approach really scales well, maybe some other method of passing config as a dict or so should be considered.
  • The baudrate is now configurable, but the other serial settings (in particular parity) are now hardcoded. This should really be configurable, but see previous point.
  • There is some duplication of default values. modbus_interface.__init__() has default values for its parameters, but AFAICS these are never used, because mqtt_interface.connect_modbus() always passes values (and has its own defaults for values missing in the config file).
  • Selecting serial or tcp now happens through the variant, which seems a bit weird to me, but given the only other variant, sungrow is a variation on ModbusTcpClient, it makes sense like this, but does feel a bit weird. Maybe this requires a bit more thought.

For now, this code works well enough for my usecase, so I'll probably not put (much) more work in this (I could make some more updates if there is specific feedback), but I wanted to at least share this code in case it is helpful for others as-is already.

iconnor and others added 3 commits October 11, 2022 16:01
This allows a top-level "slave" entry in the config to set the slave
address globally (defaulting to 1 as before), but also allows overriding
the slave address for individual registers (which allows communicating
with multiple slaves on the same bus).
self.prefix = mqtt_topic_prefix
self.address_offset = self.config.get('address_offset', 0)
self.registers = self.config['registers']
self.default_slave = self.config.get('slave', 1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making these safer - I like it

slave, addr, value, mask = self._planned_writes.get()
if mask == 0xFFFF:
self._mb.write_register(addr, value, unit=0x01)
self._mb.write_register(addr, value, unit=slave)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing up the hard-coded values

@tjhowse
Copy link
Copy Markdown
Owner

tjhowse commented Jan 24, 2023

@iconnor I've pushed up some commits to a fork of this branch to fix up the tests: master...3devo-serial-modbus

I haven't had time to 100% test and finish it off yet though. I also really don't like the "slave" terminology, and I think it's daft that upstream pymodbus is moving from "unit" to "slave".

@poucz
Copy link
Copy Markdown

poucz commented Oct 27, 2023

How does it look like with merge?
It would be useful for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants